const express = require('express');
const router = express.Router();
const axios = require('axios');
const crypto = require('crypto');
const fs = require('fs');
const config = require('../config');

// 从证书文件中提取序列号
function getSerialNumber(certPath) {
  const cert = fs.readFileSync(certPath);
  const certInfo = new crypto.X509Certificate(cert);
  return certInfo.serialNumber;
}

// 生成签名
function generateSignature(method, url, timestamp, nonceStr, body) {
  const signStr = `${method}\n${url}\n${timestamp}\n${nonceStr}\n${body}\n`;
  const sign = crypto.createSign('RSA-SHA256');
  sign.update(signStr);
  const privateKey = fs.readFileSync(config.keyPath);
  return sign.sign(privateKey, 'base64');
}

// 验证签名
function verifySignature(signature, timestamp, nonce, body, publicKeyPath) {
  const verifyStr = `${timestamp}\n${nonce}\n${body}\n`;
  const verify = crypto.createVerify('RSA-SHA256');
  verify.update(verifyStr);
  const publicKey = fs.readFileSync(publicKeyPath);
  return verify.verify(publicKey, signature, 'base64');
}

// 写入日志的函数，默认写入微信支付日志文件
function writeLog(message) {
  const logDir = './logs'; // 日志文件目录
  const logFilePath = `${logDir}/wechat_pay_notify.log`; // 默认日志文件路径

  // 如果日志目录不存在，则创建
  if (!fs.existsSync(logDir)) {
    fs.mkdirSync(logDir, { recursive: true });
  }
  // 将消息写入日志文件
  fs.appendFileSync(logFilePath, `[${new Date().toISOString()}] ${message}\n`, 'utf8');
}

router.get('/', (req, res) => {
  res.send(getSerialNumber(config.certPath));
});

// 统一下单接口并返回支付参数
router.post('/unifiedorder', async (req, res) => {
  const { openid, total_fee, out_trade_no } = req.body;

  const url = '/v3/pay/transactions/jsapi';
  const method = 'POST';
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const nonceStr = crypto.randomBytes(16).toString('hex');
  const body = JSON.stringify({
    appid: config.appId,
    mchid: config.mchId,
    description: '商品描述',
    out_trade_no,
    notify_url: config.notifyUrl,
    amount: {
      total: total_fee,
      currency: 'CNY',
    },
    payer: {
      openid,
    },
  });

  const signature = generateSignature(method, url, timestamp, nonceStr, body);
  const serialNo = getSerialNumber(config.certPath); // 自动获取证书序列号

  try {
    // 调用微信支付 V3 接口生成 prepay_id
    const response = await axios.post(`https://api.mch.weixin.qq.com${url}`, body, {
      headers: {
        'Authorization': `WECHATPAY2-SHA256-RSA2048 mchid="${config.mchId}",nonce_str="${nonceStr}",signature="${signature}",timestamp="${timestamp}",serial_no="${serialNo}"`,
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    });

    const prepay_id = response.data.prepay_id; // 获取 prepay_id

    // 生成支付参数
    const payParams = {
      appId: config.appId, // 小程序或公众号的 AppID
      timeStamp: timestamp, // 时间戳
      nonceStr: nonceStr, // 随机字符串
      package: `prepay_id=${prepay_id}`, // 预支付交易会话标识
      signType: 'RSA', // 签名类型
    };

    // 生成支付签名
    const paySignStr = `${payParams.appId}\n${payParams.timeStamp}\n${payParams.nonceStr}\n${payParams.package}\n`;
    const paySign = crypto.createSign('RSA-SHA256');
    paySign.update(paySignStr);
    const privateKey = fs.readFileSync(config.keyPath);
    payParams.paySign = paySign.sign(privateKey, 'base64'); // 支付签名

    // 返回支付参数
    res.json(payParams);
  } catch (error) {
    console.error('Error in unifiedorder:', error.response.data);
    res.status(500).json({ error: error.message });
  }
});
/**
 * AEAD_AES_256_GCM 解密函数
 * @param {Object} params - 参数对象
 * @param {string|Buffer} params.key - 32字节密钥 (支持 hex/base64/原始 Buffer)
 * @param {string|Buffer} params.nonce - 12字节随机数 (支持 hex/base64/原始 Buffer)
 * @param {string|Buffer} [params.aad] - 关联数据 (可选，支持 utf8/hex/base64)
 * @param {string|Buffer} params.ciphertext - 密文 (含16字节认证标签，支持 hex/base64)
 * @returns {string} - 解密后的 UTF-8 字符串
 * @throws {Error} - 当认证失败或参数无效时抛出
 */
function secureDecryptAes256Gcm({ key, nonce, aad, ciphertext }) {
  const toBuffer = (input, enc = 'utf8') => 
    Buffer.isBuffer(input) ? input : Buffer.from(input, enc);

 
  const aadBuf = aad ? toBuffer(aad) : null;
  const cipherBuf = toBuffer(ciphertext, 'base64'); // 确保 ciphertext 是 Base64 编码

  // 分离标签和加密数据
  const [encrypted, authTag] = cipherBuf.slice(-16).length === 16
    ? [cipherBuf.slice(0, -16), cipherBuf.slice(-16)]
    : [Buffer.alloc(0), cipherBuf];

  const decipher = crypto.createDecipheriv('aes-256-gcm', key, nonce);
  
  if (aadBuf) decipher.setAAD(aadBuf, { authTagLength: 16 });
  decipher.setAuthTag(authTag);

  try {
    return decipher.update(encrypted)
      .toString('utf8') + decipher.final().toString('utf8');
  } catch (err) {
    writeLog(`解密失败，错误信息: ${err.message}`);
    throw new Error(`解密失败 [${err.message}]`);
  }
}


// 支付结果通知
router.post('/notify', (req, res) => {
  try {
    // 记录请求体的内容
    writeLog(`请求体数据: ${JSON.stringify(req.body)}`);

    const signature = req.headers['wechatpay-signature'];
    const timestamp = req.headers['wechatpay-timestamp'];
    const nonce = req.headers['wechatpay-nonce'];
    const serial = req.headers['wechatpay-serial'];

    if (!signature || !timestamp || !nonce || !serial) {
      const errorMessage = 'Missing signature, timestamp, nonce, or serial in request headers';
      writeLog(errorMessage);
      return res.status(400).json({ error: errorMessage });
    }

    // 验证签名
    const isValid = verifySignature(signature, timestamp, nonce, JSON.stringify(req.body), config.pubKey);
    if (!isValid) {
      const errorMessage = 'Invalid signature';
      writeLog(errorMessage);
      return res.status(400).json({ error: errorMessage });
    }

    const { resource } = req.body;
    if (!resource) {
      const errorMessage = 'Missing resource in request body';
      writeLog(errorMessage);
      return res.status(400).json({ error: errorMessage });
    }

    const { algorithm, original_type, ciphertext, associated_data, nonce: resourceNonce } = resource;
    if (!algorithm || !original_type || !ciphertext || !resourceNonce) {
      const errorMessage = 'Missing required fields in resource';
      writeLog(errorMessage);
      return res.status(400).json({ error: errorMessage });
    }

    // 记录 nonce 的原始内容
    writeLog(`提取的 nonce: ${resourceNonce}`);

  

    // 调用解密函数
    const key = config.apiKey;
    const decrypted = secureDecryptAes256Gcm({
      key: key,
      nonce: resourceNonce,
      aad: associated_data,
      ciphertext: ciphertext
    });

    // 处理解密后的数据
    writeLog(`解密后的业务信息: ${decrypted}`);
    const { out_trade_no, transaction_id, trade_state, trade_state_desc } = JSON.parse(decrypted);

    if (trade_state === 'SUCCESS') {
      writeLog(`订单 ${out_trade_no} 已更新为已支付状态`);
    } else {
      writeLog(`订单 ${out_trade_no} 未支付，状态为 ${trade_state}`);
    }

    res.status(200).end();
  } catch (error) {
    const errorMessage = `Error in notify: ${error.message}`;
    writeLog(errorMessage);
    res.status(500).json({ error: errorMessage });
  }
});

// 根据 jscode 换取 openid 和 session_key
router.get('/getOpenid', async (req, res) => {
  const { code } = req.query; // 从请求参数中获取 jscode

  if (!code) {
    return res.status(400).json({ error: 'Code is required' });
  }

  try {
    const response = await axios.get('https://api.weixin.qq.com/sns/jscode2session', {
      params: {
        appid: config.appId,      // 小程序 AppID
        secret: config.appSecret, // 小程序 AppSecret
        js_code: code,            // 前端传的 jscode
        grant_type: 'authorization_code',
      },
    });

    const { openid, session_key } = response.data;
    res.json({ openid, session_key });
  } catch (error) {
    console.error('Error fetching openid:', error.response.data);
    res.status(500).json({ error: 'Failed to fetch openid' });
  }
});

// 生成提现地址并发起微信转账
router.post('/withdraw', async (req, res) => {
  const { openid, amount, out_trade_no } = req.body;

  if (!openid || !amount || !out_trade_no) {
    return res.status(400).json({ status: 'error', error: 'Missing required fields: openid, amount, out_trade_no' });
  }

  const url = '/v3/fund-app/mch-transfer/transfer-bills';
  const method = 'POST';
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const nonceStr = crypto.randomBytes(16).toString('hex');
  const body = JSON.stringify({
    appid: config.appId,
    out_bill_no: out_trade_no,
    transfer_scene_id: '1000', // 使用微信支付支持的场景 ID
    openid: openid,
    transfer_amount: amount, // 确保是以分为单位的整数
    transfer_remark: '提现',
    notify_url: config.notifyUrl, // 通知地址
    transfer_scene_report_infos: [
      {
        info_type: '活动名称', // 信息类型
        info_content: '新会员有礼', // 信息内容
      },
      {
        info_type: '奖励说明', // 信息类型
        info_content: '注册会员抽奖一等奖', // 信息内容
      },
    ],
  });

  const signature = generateSignature(method, url, timestamp, nonceStr, body);
  const serialNo = getSerialNumber(config.certPath); // 自动获取证书序列号

  // 记录请求信息
  writeLog(`Request URL: https://api.mch.weixin.qq.com${url}`);
  writeLog(`Request Body: ${body}`);
  writeLog(`Signature: ${signature}`);
  writeLog(`Serial No: ${serialNo}`);

  try {
    // 调用微信支付 V3 转账接口
    const response = await axios.post(`https://api.mch.weixin.qq.com${url}`, body, {
      headers: {
        'Authorization': `WECHATPAY2-SHA256-RSA2048 mchid="${config.mchId}",nonce_str="${nonceStr}",signature="${signature}",timestamp="${timestamp}",serial_no="${serialNo}"`,
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Wechatpay-Serial': serialNo,
      },
    });

    // 记录响应信息
    writeLog(`Response Data: ${JSON.stringify(response.data)}`);

    // 返回转账结果，并添加状态字段和商户号
    res.json({ status: 'success', mchId: config.mchId, data: response.data });
  } catch (error) {
    // 记录错误信息
    writeLog(`Error in withdraw: ${error.stack}`);
    writeLog(`Error Response Data: ${JSON.stringify(error.response ? error.response.data : 'No response data')}`);

    // 返回错误信息，并添加状态字段
    res.status(500).json({ status: 'error', error: error.message });
  }
});

module.exports = router;
